from IoT import Device
from database import DBTool
import random
import serial
from serial.tools.list_ports import comports
from telecom import TelecomMap, TelecomVideo
from StreamProcessor import ActionProcessor


class Facility:
    def __init__(self):
        # 属性数值初始化
        self.pitch = self.roll = self.yaw = None
        self.X = self.Y = self.Z = self.W = None
        self.pH = round(random.uniform(7.9, 8.3), 1)
        self.temperature = round(random.uniform(27, 28), 2)
        self.tds = random.randint(700, 800)
        self.density_ship = self.density_fish = None
        self.speed = self.mileage = self.accelerate = self.endurance = None

        self.attribute_env = {'density_ship', 'density_fish',
                              'ph', 'temperature', 'tds'}

        self.attribute_navigate = {'pitch', 'roll', 'yaw',
                                   'X', 'Y', 'Z', 'W',
                                   'speed', 'mileage', 'accelerate', 'endurance'}

        coms = [i.device for i in comports()]
        # 实例化数据库操作对象
        self.dbtool = DBTool()
        # 实例化IoT操作对象
        self.client = Device()
        # 实例化地图发送对象
        self.telemap = TelecomMap('127.0.0.1')
        # 实例化视频发送对象
        self.televideo = TelecomVideo()
        # 实例化功能接收对象
        self.action = ActionProcessor()
        # 实例化串口通信对象
        self.uart = UART(coms[0], 115200, 0.1)

    def update_all_db(self):
        # if self.endurance is None:
        #   return
        # 环境数据上传
        self.dbtool.insert('density_ship', self.density_ship)
        self.dbtool.insert('density_fish', self.density_fish)
        self.dbtool.insert('ph', self.pH)
        self.dbtool.insert('tds', self.tds)
        self.dbtool.insert('temperature', self.temperature)

        # 航行数据上传
        # self.dbtool.update('navigate', 'pitch', self.pitch)
        # self.dbtool.update('navigate', 'yaw', self.yaw)
        # self.dbtool.update('navigate', 'roll', self.roll)
        # self.dbtool.update('navigate', 'X', self.X)
        # self.dbtool.update('navigate', 'Y', self.Y)
        # self.dbtool.update('navigate', 'Z', self.Z)
        # self.dbtool.update('navigate', 'W', self.W)
        # self.dbtool.update('navigate', 'speed', self.speed)
        # self.dbtool.update('navigate', 'mileage', self.mileage)
        # self.dbtool.update('navigate', 'accelerate', self.accelerate)
        # self.dbtool.update('navigate', 'endurance', self.endurance)

    # 获取从上位机得到的控制信息并转发到单片机
    def action_recv_trans(self):
        act, arg = self.action.action_receive()
        if act == 'stop':
            self.uart.dict.get(act)()
        else:
            self.uart.dict.get(act)(float(arg))

    # 获取从单片机中的得到的环境数据并转发到databse和IoT
    def usv_recv_trans(self):
        data = self.uart.uart.readline().decode().split('|')
        identifier, value = data[0], float(data[1])
        if identifier in self.attribute_env:
            self.client.post_data(identifier, value)
            self.dbtool.insert(identifier, value)
            setattr(self, identifier, value)
        elif identifier in self.attribute_navigate:
            self.client.post_data(identifier, value)
            self.dbtool.update('navigate', identifier, value)
            setattr(self, identifier, value)

    def map_send(self):
        self.telemap.map_send()

    def video_send(self):
        self.televideo.send_video('127.0.0.1')


# 模拟单片机和图像数据
class Simulator:
    def __init__(self):
        self.client = Device
        self.pitch = self.roll = self.yaw = None
        self.X = self.Y = self.Z = self.W = None
        self.pH = self.temperature = self.tds = None
        self.density_ship = self.density_fish = None


'''
帧头0X3F
前进：N1_M
后退：N2_M
左转:N3_M
右转：N4_M
设置方向：D___M
停转：T0M
帧尾0X0D
'''


class UART:
    def __init__(self, com, bps, timeout):
        self.port = com
        self.bps = bps
        self.timeout = timeout
        self.dict = {'forward': self.forward,
                     'backward': self.backward,
                     'left': self.left,
                     'right': self.right,
                     'stop': self.stop,
                     'direction': self.set_dir}
        try:
            self.uart = serial.Serial(self.port, self.bps, timeout=self.timeout)
        except Exception as e:
            print('Creating Serial ERROR', e)

    def open_serial(self):
        self.uart.open()

    def close_serial(self):
        self.uart.close()

    def send_data(self, data):
        self.uart.write(data)

    def forward(self, speed):
        # <b2sfcb is 1 2 4 1 1
        command = ('0x3F' + 'N1' + str(speed) + 'M' + '0x0D')
        print(command)
        self.send_data(command.encode())

    def backward(self, speed):
        command = ('0x3F' + 'N2' + str(speed) + 'M' + '0x0D')
        print(command)
        self.send_data(command.encode())

    def left(self, speed):
        command = '0x3F' + 'N3' + str(speed) + 'M' + '0x0D'
        print(command)
        self.send_data(command.encode())

    def right(self, speed):
        command = '0x3F' + 'N4' + str(speed) + 'M' + '0x0D'
        print(command)
        self.send_data(command.encode())

    def stop(self):
        command = '0x3F' + 'T0M' + '0x0D'
        print(command)
        self.send_data(command.encode())

    # <bchcb = 1 1 2 1 1
    def set_dir(self, angle):
        command = '0x3F' + 'D' + str(angle) + 'M' + '0x0D'
        print(command)
        self.send_data(command)


device = Facility()
device.video_send()
